﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Dockable.Forms
{
    public partial class DockableForm : Form
    {
        #region Properties

        private bool IsDocked
        {
            get;
            set;
        }

        private bool IsDragging
        {
            get;
            set;
        }

        private bool IsPinned
        {
            get;
            set;
        }

        public bool IsMaximized
        {
            get 
            { 
                return this.WindowState == FormWindowState.Maximized; 
            }

            set
            {
                if (value)
                {
                    this.WindowState = FormWindowState.Maximized;
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_min;
                }
                else
                {
                    this.WindowState = FormWindowState.Normal;
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_max;
                }
            }
        }

        private bool IsResizing
        {
            get;
            set;
        }

        private Point MouseDownLocation
        {
            get;
            set;
        }

        private Size OriginalWindowSize
        {
            get;
            set;
        }

        private BorderHoverDirection ResizingDirection
        {
            get;
            set;
        }

        #endregion

        public DockableForm()
        {
            InitializeComponent();
        }

        private TextBox m_statusBox;
        public DockableForm(TextBox statusBox)
        {
            InitializeComponent();
            m_statusBox = statusBox;
        }

        private void DockableForm_Activated(object sender, EventArgs e)
        {
            m_headerPanel.BackgroundImage = Dockable.Forms.Properties.Resources.header_focus;
            m_cmText.ForeColor = Color.Black;
            m_cmClose.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_close;

            if (IsDocked)
            {
                if (IsPinned)
                {
                }
                else
                {
                }
            }
            else
            {
                if (IsMaximized)
                {
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_min;
                }
                else
                {
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_max;  
                }
            }
        }

        private void DockableForm_Deactivate(object sender, EventArgs e)
        {
            m_headerPanel.BackgroundImage = Dockable.Forms.Properties.Resources.header;
            m_cmText.ForeColor = Color.White;
            m_cmClose.BackgroundImage = Dockable.Forms.Properties.Resources.cm_nofocus_close;

            if (IsDocked)
            {
                if (IsPinned)
                {
                }
                else
                {
                }
            }
            else
            {
                if (!IsMaximized)
                {
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_nofocus_max;
                }
            }
        }

        private void m_headerPanel_MouseDown(object sender, MouseEventArgs e)
        {
            IsDragging = true;
            MouseDownLocation = new Point(e.X, e.Y);
        }

        private void m_headerPanel_MouseUp(object sender, MouseEventArgs e)
        {
            IsDragging = false;
        }

        private void m_headerPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (IsDragging)
            {
                if (IsMaximized)
                {
                    // Get the screen point prior to going to normal display
                    Point screenPoint = this.PointToScreen(new Point(e.X, e.Y));

                    IsMaximized = false;
                    this.Location = new Point(e.X - (this.Width / 2), e.Y - 10);

                    // Reset the mouse down location based off the curren screen size
                    MouseDownLocation = this.PointToClient(screenPoint);
                }
                else
                {
                    int dX = MouseDownLocation.X - e.X;
                    int dY = MouseDownLocation.Y - e.Y;

                    this.Location = new Point(this.Location.X - dX, this.Location.Y - dY);
                }
            }
        }

        private void m_cmClose_MouseEnter(object sender, EventArgs e)
        {
            m_cmClose.BackgroundImage = Dockable.Forms.Properties.Resources.cm_selected_close;
        }

        private void m_cmClose_MouseLeave(object sender, EventArgs e)
        {
            if (Focused)
            {
                m_cmClose.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_close;
            }
            else
            {
                m_cmClose.BackgroundImage = Dockable.Forms.Properties.Resources.cm_nofocus_close;
            }
        }

        private void m_cmClose_MouseClick(object sender, MouseEventArgs e)
        {
            this.Close();
        }

        private void m_cmPin_MouseEnter(object sender, EventArgs e)
        {
            if (IsDocked)
            {

            }
            else
            {
                if (IsMaximized)
                {
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_selected_min;
                }
                else
                {
                    m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_selected_max;
                }
            }
        }

        private void m_cmPin_MouseLeave(object sender, EventArgs e)
        {
            if (Focused)
            {
                if (IsDocked)
                {
                }
                else
                {
                    if (IsMaximized)
                    {
                        m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_min;
                    }
                    else
                    {
                        m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_focus_max;
                    }
                }
            }
            else
            {
                if (IsDocked)
                {
                }
                else
                {
                    if (!IsMaximized)
                    {
                        m_cmPin.BackgroundImage = Dockable.Forms.Properties.Resources.cm_nofocus_max;
                    }
                }
            }
        }

        private void m_cmPin_MouseClick(object sender, MouseEventArgs e)
        {
            if (IsDocked)
            {

            }
            else
            {
                IsMaximized = !IsMaximized;
            }
        }

        private void m_borderPanel_MouseEnter(object sender, EventArgs e)
        {
            UpdateCursor(this.Cursor.HotSpot);
        }

        private void m_borderPanel_MouseLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Arrow;
        }

        private void m_borderPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (IsResizing)
            {
                int dX = MouseDownLocation.X - e.X;
                int dY = MouseDownLocation.Y - e.Y;

                if (ResizingDirection == BorderHoverDirection.NW)
                {
                    this.Location = new Point(this.Location.X - dX, this.Location.Y - dY);

                    this.Width += dX;
                    this.Height += dY;
                }
                else if (ResizingDirection == BorderHoverDirection.N)
                {
                    this.Location = new Point(this.Location.X, this.Location.Y - dY);

                    this.Height += dY;
                }
                else if (ResizingDirection == BorderHoverDirection.NE)
                {
                    this.Location = new Point(this.Location.X, this.Location.Y - dY);

                    this.Height += dY;
                    this.Width = OriginalWindowSize.Width - dX;
                }
                else if (ResizingDirection == BorderHoverDirection.E)
                {
                    this.Width = OriginalWindowSize.Width - dX;
                }
                else if (ResizingDirection == BorderHoverDirection.SE)
                {
                    this.Width = OriginalWindowSize.Width - dX;
                    this.Height = OriginalWindowSize.Height - dY;                    
                }
                else if (ResizingDirection == BorderHoverDirection.S)
                {
                    this.Height = OriginalWindowSize.Height - dY;
                }
                else if (ResizingDirection == BorderHoverDirection.SW)
                {
                    this.Location = new Point(this.Location.X - dX, this.Location.Y);

                    this.Width += dX;
                    this.Height = OriginalWindowSize.Height - dY;
                }
                else if (ResizingDirection == BorderHoverDirection.W)
                {
                    this.Location = new Point(this.Location.X - dX, this.Location.Y);

                    this.Width += dX;
                }
            }
            else
            {
                UpdateCursor(e.Location);
            }
        }

        private void m_borderPanel_MouseUp(object sender, MouseEventArgs e)
        {
            IsResizing = false;
        }

        private void m_borderPanel_MouseDown(object sender, MouseEventArgs e)
        {
            IsResizing = true;
            MouseDownLocation = new Point(e.X, e.Y);
            ResizingDirection = GetMouseOverBorderDirection(MouseDownLocation);
            OriginalWindowSize = new Size(this.Width, this.Height);            
        }

        private void m_headerPanel_DoubleClick(object sender, EventArgs e)
        {
            IsMaximized = !IsMaximized;
        }

        private void UpdateCursor(Point p)
        {
            BorderHoverDirection mouseHoverLocation = GetMouseOverBorderDirection(p);

            if (mouseHoverLocation == BorderHoverDirection.NW)
            {
                this.Cursor = Cursors.SizeNWSE;
            }
            else if (mouseHoverLocation == BorderHoverDirection.N)
            {
                this.Cursor = Cursors.SizeNS;
            }
            else if (mouseHoverLocation == BorderHoverDirection.NE)
            {
                this.Cursor = Cursors.SizeNESW;
            }
            else if (mouseHoverLocation == BorderHoverDirection.E)
            {
                this.Cursor = Cursors.SizeWE;
            }
            else if (mouseHoverLocation == BorderHoverDirection.SE)
            {
                this.Cursor = Cursors.SizeNWSE;
            }
            else if (mouseHoverLocation == BorderHoverDirection.S)
            {
                this.Cursor = Cursors.SizeNS;
            }
            else if (mouseHoverLocation == BorderHoverDirection.SW)
            {
                this.Cursor = Cursors.SizeNESW;
            }
            else if (mouseHoverLocation == BorderHoverDirection.W)
            {
                this.Cursor = Cursors.SizeWE;
            }
        }

        private BorderHoverDirection GetMouseOverBorderDirection(Point p)
        {
            if (p.X >= 0 && p.X <= 4 && p.Y >= 0 && p.Y <= 4)
            {
                return BorderHoverDirection.NW;
            }
            else if (p.X > 4 && p.X < (this.Width - 4) && p.Y >= 0 && p.Y <= 4)
            {
                return BorderHoverDirection.N;
            }
            else if (p.X >= (this.Width - 4) && p.X <= (this.Width) && p.Y >= 0 && p.Y <= 4)
            {
                return BorderHoverDirection.NE;
            }
            else if (p.X >= (this.Width - 4) && p.X <= (this.Width) && p.Y > 4 && p.Y < (this.Height - 4))
            {
                return BorderHoverDirection.E;
            }
            else if (p.X >= (this.Width - 4) && p.X <= (this.Width) && p.Y >= (this.Height - 4) && p.Y <= (this.Height))
            {
                return BorderHoverDirection.SE;
            }
            else if (p.X > 4 && p.X < (this.Width - 4) && p.Y >= (this.Height - 4) && p.Y <= (this.Height))
            {
                return BorderHoverDirection.S;
            }
            else if (p.X >= 0 && p.X <= 4 && p.Y >= (this.Height - 4) && p.Y <= (this.Height))
            {
                return BorderHoverDirection.SW;
            }
            else if (p.X >= 0 && p.X <= 4 && p.Y > 4 && p.Y < (this.Height - 4))
            {
                return BorderHoverDirection.W;
            }
            else
            {
                return BorderHoverDirection.ND;
            }
        }

        private enum BorderHoverDirection { NW, N, NE, W, E, SW, S, SE, ND };       
    }
}